home *** CD-ROM | disk | FTP | other *** search
/ Meeting Pearls 1 / Meeting Pearls Vol 1 (1994).iso / amok98-106 / amok105 / hotkey / hotkey.mod < prev    next >
Text File  |  1994-05-03  |  13KB  |  428 lines

  1. (*---------------------------------------------------------------------------
  2. :Program.    Hotkey.mod
  3. :Author.     Thomas Igracki
  4. :Address.    Obstallee 45, 1000 Berlin 20, W-Germany
  5. :E-Mail.     T.IGRACKI@BAMP.ZER
  6. :Version.    V1.0  28-Apr-92  Thomas Igracki
  7. :Version.              first release
  8. :Version.    V2.0  21-Dec-92  Thomas Wagner [tom]
  9. :Version.              removed some bugs (no ReplyMsg ...)
  10. :Version.              and completely revised. Warning:
  11. :Version.              Interface has changed!
  12. :Copyright.  Thomas Igracki
  13. :Language.   Oberon
  14. :Translator. Amiga Oberon 3.00d
  15. :Remark.     OS2.04 or higher Only!
  16. ---------------------------------------------------------------------------*)
  17.  
  18. MODULE HotKey;
  19. IMPORT
  20.    s: SYSTEM, c: Commodities, e: Exec;
  21. VAR
  22.    nb        : c.NewBroker;
  23.    broker,
  24.    filter   : c.CxObjPtr;
  25.    ComPort  : e.MsgPortPtr;
  26.    Error -  : SHORTINT;      (* Look here to determine why Init()/InitX() failed *)
  27.    ErrorSet-: LONGSET;         (* Look here to determine why AddKey failed *)
  28. CONST
  29.  
  30. (* Error returns in global variable Error from Init() and InitX() *)
  31.   noError    * = c.errOk    ;  (* No error                             *)
  32.   systemError    * = c.errSysErr ;  (* System error, no memory, etc         *)
  33.   uniqueError    * = c.errDup    ;  (* uniqueness violation                 *)
  34.   wrongVersion    * = c.errVersion;  (* didn't understand NewBroker.version  *)(* should not appear *)
  35.   (* own definitions *)
  36.   calledTwice       * = -1;       (* called Init() or InitX() twice *)
  37.   createPortFailed * = -2;       (* CreateMsgPort() failed *)
  38.   brokerNIL       * = -3;       (* No Broker created *)
  39.  
  40. (* Error returns in global variable ErrorSet from AddKey(). NOTE: multiple might be set! *)
  41.   filterIsNIL     * = c.coErrIsNull    ;  (* not enough memory to create filter  *)
  42.   nilAttach     * = c.coErrNullAttach;  (* someone attached NULL to my list    *)
  43.   badDescription * = c.coErrBadFilter ;  (* a bad filter description was given; wrong hotkey descr.  *)
  44.   badType     * = c.coErrBadType   ;  (* unmatched type-specific operation   *)
  45.   (* own definitions *)
  46.   noPort     * = MAX(LONGSET);       (* Call Init() or Initx() first *)
  47.  
  48. (* Message Types *)
  49.   hotkey  * = c.cxmIEvent;
  50.   command * = c.cxmCommand;
  51.  
  52. (* Commands *)
  53.   cDisable  *= c.cmdDisable;    (* handled automaticly, you should ignore it *)
  54.   cEnable   *= c.cmdEnable;    (* handled automaticly, you should ignore it *)
  55.   cAppear   *= c.cmdAppear;    (* open your window, if you can  *)
  56.   cDisappear*= c.cmdDisappear;    (* go dormant                    *)
  57.   cKill     *= c.cmdKill;    (* go away for good              *)
  58.   cListChg  *= c.cmdListChg;    (* Someone changed the broker list *)
  59.   cUnique   *= c.cmdUnique;    (* someone tried to create a broker
  60.                    with your name. Suggest you appear. *)
  61.  
  62.  (*NOTE*)(* the following constants are defined wrong in AmigaOberon 3.00 Interfaces *)
  63.  
  64.  (* Flags for Unique *)
  65.    duplicate  * = {};
  66.    unique     * = 0;   (* will not allow duplicates           *)
  67.    notify     * = 1;   (* sends cUnique to existing broker *)
  68.  
  69. (****** HotKey/--background-- ******************************************
  70. *
  71. *   DESCRIPTION
  72. *    This module allows easy access to hotkey-specific functions of the
  73. *    commodity.library.
  74. *
  75. *   NOTE
  76. *    DeleteBroker() and CheckCVersion() are the only procedures which
  77. *    are very kind to OS1.x, because ONLY they are supposed to be called on
  78. *    Operating Systems other than Release 2+.
  79. *
  80. *    Therefore you MUST NOT call any of the module's
  81. *    procedures except DeleteBroker() and CheckCVersion() on
  82. *    Systems without commodities.library.
  83. *
  84. *    In addition the version of commodities.library must be 37
  85. *    or higher, because this version is demanded by Oberon 3.00 
  86. *    Interfaces for the commodities.library
  87. *    ( OpenLibrary(commodities.library,37) ).
  88. *
  89. *    After version check failed, you may gracefully exit, e.g.
  90. *      IF ~ CheckCVersion(0) THEN HALT(20) END;
  91. *
  92. *    There should be no need to IMPORT Commodities, because all
  93. *    important constants are redefined. Some constants are even
  94. *    defined wrong in Interfaces for Oberon3.00!
  95. *
  96. *
  97. *   EXAMPLE
  98. *    Refer to HotKeyTest for a example how to use this module.
  99. *
  100. *   AUTHOR
  101. *    Program:  V1.0    28-Apr-92  Thomas Igracki
  102. *            first release
  103. *          V2.0    21-Dec-92  Thomas Wagner [tom]
  104. *            removed some bugs (no ReplyMsg ...)
  105. *            and completely revised.
  106. *            NOTE: ** Interface has changed! **
  107. *
  108. *    Autodocs: Thomas Wagner [tom]
  109. *
  110. ******************************************************************************)
  111.  
  112. (****** HotKey/CheckCVersion ******************************************
  113. *
  114. *   NAME
  115. *    CheckCVersion -- Checks the version of the Commodities.library.
  116. *
  117. *   SYNOPSIS
  118. *    CheckCVersion (version: SHORTINT): BOOLEAN;
  119. *
  120. *   FUNCTION
  121. *    Check whether the required version is available.
  122. *
  123. *   INPUTS
  124. *    version - The required version. 0 to check if there is
  125. *          any usable version of commodities.library available.
  126. *          (See NOTE!).
  127. *
  128. *   RESULT
  129. *    BOOLEAN - TRUE    if Commodity has the required version or higher
  130. *          FALSE if not available
  131. *
  132. *   NOTE
  133. *    V36 is considered out of date. So if you use the Interfaces for
  134. *    commodity.library delivered with Oberon3.00 (or later versions)
  135. *    CheckCVersion(0) will return FALSE!
  136. *
  137. ******************************************************************************)
  138.  
  139. PROCEDURE CheckCVersion*(version: SHORTINT):BOOLEAN;
  140. BEGIN
  141.   IF c.base = NIL THEN RETURN(FALSE) END;
  142.   RETURN(c.base.version >= version);
  143. END CheckCVersion;
  144.  
  145.  
  146. (****** HotKey/Init ******************************************
  147. *
  148. *   NAME
  149. *    Init -- Initiate a broker.
  150. *    InitX -- Initiate a broker (extended parameters).
  151. *
  152. *   SYNOPSIS
  153. *    InitX (name,title,descr: ARRAY OF CHAR;
  154. *           unique           : SET;
  155. *           window           : BOOLEAN;
  156. *           pri           : SHORTINT    ): SHORTINT;
  157. *
  158. *    Init (name,title,descr: ARRAY OF CHAR): SHORTINT;
  159. *
  160. *   FUNCTION
  161. *    Initiates some structures needed by all other procedures
  162. *    of this module and installs a broker.
  163. *
  164. *   INPUTS
  165. *    name   - The name of the broker. You should not exceed the length
  166. *         defined in Commodities.nameLen.
  167. *    title  - Name, version, ... of the commodity. You should not exceed
  168. *         the maximum length defined in Commodities.titleLen.
  169. *    descr  - A short summary of the functionality of this commodity.
  170. *         You should not exceed the length defined in
  171. *         Commodities.descrLength.
  172. *
  173. *    Only for InitX():
  174. *
  175. *    unique - Set to one or more of Flags for Unique.
  176. *         Init: set to {notify}.
  177. *    window - Set this to TRUE when your commodity is able to open
  178. *         a window. If this is set to FALSE the Show/Hide gadgets
  179. *         of the exchange program are deactivated.
  180. *         Init: set to TRUE.
  181. *    pri    - The priority of the broker. Init: set to 0.
  182. *
  183. *   RESULT
  184. *    SHORTINT - A positive number is the Signalbit for hotkey
  185. *           activity. -1 indicates an error. See the global
  186. *           readonly variable Error for the cause.
  187. *           Here are some important errors:
  188. *            systemError : usually no memory
  189. *            calledTwice : called this routine twice
  190. *            brokerNIL    : usually already another broker with
  191. *                  same name
  192. *
  193. *   NOTES
  194. *    - After Init() or InitX() you must call Activate() to activate
  195. *      the broker.
  196. *    - You can't call Init() twice.
  197. *
  198. *   SEE ALSO
  199. *    DeleteBroker()
  200. *
  201. ******************************************************************************)
  202.  
  203. PROCEDURE InitX* (name,title,descr: ARRAY OF CHAR;
  204.           unique      : SET;
  205.           window      : BOOLEAN;
  206.           pri          : SHORTINT       ): SHORTINT;
  207.          (* $CopyArrays- *)
  208. VAR err: LONGINT;
  209. BEGIN
  210.      IF ComPort # NIL THEN Error := calledTwice; RETURN -1 END;
  211.      ComPort := e.CreateMsgPort();
  212.      IF ComPort = NIL THEN Error := createPortFailed; RETURN -1 END;
  213.      nb.version := c.nbVersion;
  214.      nb.name := s.ADR(name);
  215.      nb.title := s.ADR(title);
  216.      nb.descr := s.ADR(descr);
  217.      nb.unique := unique;
  218.      IF window THEN nb.flags := {c.showHide} END;
  219.      nb.pri := pri;
  220.      nb.port := ComPort;
  221.      broker := c.CxBroker (nb,err);
  222.      IF err = c.errOk THEN
  223.        IF broker # NIL THEN
  224.      RETURN ComPort.sigBit;
  225.        ELSE
  226.      Error := brokerNIL; RETURN -1;
  227.        END;
  228.      ELSE
  229.        Error := SHORT(SHORT(err)); RETURN -1;
  230.      END;
  231.  
  232. END InitX;
  233.  
  234. PROCEDURE Init* (name,title,descr: ARRAY OF CHAR): SHORTINT;
  235.         (* $CopyArrays- *)
  236. BEGIN
  237.   RETURN(InitX(name,title,descr,{notify},TRUE,0));
  238. END Init;
  239.  
  240.  
  241. (****** HotKey/AddKey ******************************************
  242. *
  243. *   NAME
  244. *    AddKey -- Add a hotkey description to the broker
  245. *
  246. *   SYNOPSIS
  247. *    AddKey (descr: ARRAY OF CHAR; ID: LONGINT):BOOLEAN
  248. *
  249. *   FUNCTION
  250. *    Adds the given hotkey to the broker.
  251. *
  252. *   INPUTS
  253. *    descr - containing the hotkey description
  254. *    ID    - any number to recognize this hotkey. Not
  255. *        used by the module or by the operating system.
  256. *
  257. *   RESULT
  258. *    BOOLEAN - indicates the success of the hotkey installation. If
  259. *          FALSE, ErrorSet contains the error code.
  260. *          Note: Multiple error code bits are possible.
  261. *          The most important error:
  262. *           badDescription: wrong hotkey description
  263. *
  264. *   SEE ALSO
  265. *    GetCMsg()
  266. *
  267. ******************************************************************************)
  268.  
  269. PROCEDURE AddKey* (descr: ARRAY OF CHAR; ID: LONGINT):BOOLEAN; (* $CopyArrays- *)
  270. VAR filter: c.CxObjPtr;
  271. BEGIN
  272.      ErrorSet := LONGSET{};
  273.      IF ComPort = NIL THEN ErrorSet := LONGSET{noPort}; RETURN(FALSE) END;
  274.      filter := c.CxFilter (s.ADR(descr));
  275.      (* No NIL-check of filter, because addErr = c.coErrIsNull in this case *)
  276.      ErrorSet := c.CxObjError(filter);
  277.      IF ErrorSet # LONGSET{} THEN RETURN(FALSE) END;
  278.      c.AttachCxObj (filter, c.CxSender (ComPort, ID));
  279.      c.AttachCxObj (filter, c.CxTranslate (NIL));
  280.      c.AttachCxObj (broker,filter);
  281.      RETURN(TRUE);
  282. END AddKey;
  283.  
  284.  
  285. (****** HotKey/Activate ******************************************
  286. *
  287. *   NAME
  288. *    Activate -- (De)activates hotkeys
  289. *
  290. *   SYNOPSIS
  291. *    Activate (ON: BOOLEAN)
  292. *
  293. *   FUNCTION
  294. *    This function activates or deactivates the broker and its hotkeys.
  295. *
  296. *   INPUTS
  297. *    ON - TRUE to activate, FALSE to deactivate
  298. *
  299. ******************************************************************************)
  300.  
  301. PROCEDURE Activate* (ON: BOOLEAN);
  302. BEGIN      s.SETREG (0,c.ActivateCxObj (broker,s.VAL(SHORTINT,ON)));
  303. END Activate;
  304.  
  305.  
  306. (****** HotKey/GetCMsg ******************************************
  307. *
  308. *   NAME
  309. *    GetCMsg -- Get commodity message
  310. *
  311. *   SYNOPSIS
  312. *    GetCMsg(VAR type: LONGSET; VAR id: INTEGER):BOOLEAN
  313. *
  314. *   FUNCTION
  315. *    If you get the signal (value returned by Init()) then you must
  316. *    call GetCMsg() to determine which hotkey was pressed or which
  317. *    command was sent.
  318. *
  319. *   INPUTS
  320. *    VAR type - Contains hotkey if an Hotkey was pressed or command
  321. *           if a command was sent. Note: cDisable and cEnable
  322. *           are handled automatically by this module. So you
  323. *           should ignore them, except you want to add some
  324. *           more functionality to them.
  325. *    VAR id     - An integer value to store the id of a hotkey (if there
  326. *           is any Msg). Only valid if type equals command.
  327. *
  328. *   RESULT
  329. *    BOOLEAN - TRUE if there was a Msg and type and id is valid.
  330. *          Call GetCMsg() again, because there might be more Msg's.
  331. *
  332. *   EXAMPLE
  333. *    IMPORT Exec, HotKey;
  334. *    VAR HotID  : LONGINT;
  335. *        HotType: LONGSET;
  336. *        HotSig : SHORTINT;
  337. *        Signals: SHORTINT;
  338. *    ...
  339. *    IF ~HotKey.CheckCVersion(0) THEN HALT(20) END;
  340. *    HotSig := HotKey.Init(...);
  341. *    ...
  342. *    Signals := Exec.Wait(LONGSET{HotSig});
  343. *    ...
  344. *    IF HotSig IN Signals THEN
  345. *      WHILE HotKey.GetCMsg(HotType,HotID) DO
  346. *        IF HotKey.hotkey IN HotType THEN
  347. *          CASE HotID OF
  348. *        ...
  349. *          END; (* CASE *)
  350. *        ELSIF HotKey.command IN HotType THEN
  351. *          CASE HotID OF
  352. *        hot.cAppear   : (* ShowInterface *) |
  353. *        hot.cDisappear: (* HideInterface *) |
  354. *        hot.cKill     : (* Quit          *) |
  355. *        hot.cUnique   : (* ShowInterface or Quit *) |
  356. *        ELSE        (* ignore cDisable and cEnable *)
  357. *          END; (* CASE *)
  358. *        END; (* IF *)
  359. *      END; (* WHILE *)
  360. *    END; (* IF *)
  361. *
  362. *    For a full example see HotKeyTest.mod.
  363. *
  364. ******************************************************************************)
  365.  
  366. PROCEDURE GetCMsg*(VAR type: LONGSET; VAR id: LONGINT):BOOLEAN;
  367. VAR msg : s.ADDRESS; (* should be c.CxMsgPtr, but CxMsg is NO expansion of Msg *)
  368. BEGIN
  369.      IF ComPort = NIL THEN RETURN(FALSE) END;
  370.      msg := e.GetMsg (ComPort);
  371.      IF msg # NIL THEN
  372.        type := c.CxMsgType(msg);
  373.        id := c.CxMsgID(msg);
  374.        e.ReplyMsg(msg);
  375.        IF command IN type THEN
  376.      CASE id OF
  377.        cDisable : Activate(FALSE) |
  378.        cEnable  : Activate(TRUE)  |
  379.        ELSE
  380.      END;
  381.        END;
  382.        RETURN(TRUE)
  383.      ELSE
  384.        RETURN(FALSE);
  385.      END;
  386. END GetCMsg;
  387.  
  388.  
  389. (****** HotKey/DeleteBroker ******************************************
  390. *
  391. *   NAME
  392. *    DeleteBroker -- Removes a broker
  393. *
  394. *   SYNOPSIS
  395. *    DeleteBroker()
  396. *
  397. *   FUNCTION
  398. *    This function removes the broker (and all attached hotkeys) and
  399. *    closes the MsgPort.
  400. *
  401. *   NOTES
  402. *    This function is automatically called. No need to call it
  403. *    yourself except you want to delete the broker earlier.
  404. *
  405. *   SEE ALSO
  406. *    Init()
  407. *
  408. ******************************************************************************)
  409.  
  410. PROCEDURE DeleteBroker*;
  411. VAR msg : e.MessagePtr;
  412. BEGIN
  413.     IF c.base # NIL THEN (* Skip these library calls if OS < 2.04 *)
  414.       c.DeleteCxObjAll (broker) ; broker  := NIL;
  415.       IF ComPort # NIL THEN
  416.     REPEAT
  417.       msg:=e.GetMsg(ComPort);
  418.       IF msg # NIL THEN e.ReplyMsg(msg) END;
  419.     UNTIL msg = NIL;
  420.       END;
  421.       e.DeleteMsgPort (ComPort) ; ComPort := NIL;
  422.     END;
  423. END DeleteBroker;
  424.  
  425. CLOSE
  426.     DeleteBroker
  427. END HotKey.
  428.